<!--
 * @Description: TinyMce富文本编辑器
 * @Author: ye_xf
 * @Date: 2020-09-28 17:13:09
 * @LastEditTime: 2022-02-21 10:53:13
 * @LastEditors: chen_yt
 * @Reference:
-->

<!--
富文本编辑器组件使用说明：
  1. 安装
    npm install --save @packy-tang/vue-tinymce
    npm install tinymce -S

  2. 在main.js中注册
    import VueTinymce from '@packy-tang/vue-tinymce'
    Vue.use(VueTinymce)

  3. 将tinymce文件复制添加到public文件夹下，并在index.html中引入相关js文件
    <script src="./tinymce/tinymce.js"></script>
    <script src="./tinymce/langs/zh_CN.js"></script>

  4. 复制封装的TinyMceEdit组件（src/modules/components/TinyMceEdit）

  5. 使用
    <tiny-edit height="264" :value.sync="content"></tiny-edit>
    1. height：设置编辑器的高度，string类型
    2. content：获取编辑器内容
-->

<template>
  <div>
    <vue-tinymce
      ref="tinymce"
      v-model="content"
      :setting="settings"
    />
    <tiny-media-uploader
      v-if="uploadVisible"
      :uploader-cb="uploaderCb"
      :visible.sync="uploadVisible"
      :file-token.sync="mediaToken"
    />
  </div>
</template>

<script>
import loseImg from '@/assets/img/error/lose.png'
import { uploadImage } from './api'
import tinyMediaUploader from './component/tinyMediaUploader'
export default {
  name: 'TinyMceEdit',
  components: { tinyMediaUploader },
  filters: {},
  props: {
    height: {
      default: 500
    },
    value: {
      type: String,
      default: ''
    },
    customSetting: {
      type: Object,
      default: function () {
        return {}
      }
    }
  },
  data() {
    return {
      loseImg,
      content: '',
      accessToken: this.$storage.get('access_token'),
      // downloadUrl: process.env.VUE_APP_BASE_API + '/sys-storage/download',
      setting: {
        resize: true,
        menubar: false, //设置1级菜单显隐/调整菜单顺序 menubar: 'file edit insert view format table tools help'
        // inline: true, //开启内联模式
        //设置工具栏上显示的按钮 若设置false，则隐藏
        // ' fullscreen | numlist bullist | image | bold | codesample |  fontsizeselect forecolor backcolor |',
        toolbar:
          'undo redo | fullscreen | formatselect alignleft aligncenter alignright alignjustify | link unlink | numlist bullist | image media table emoticons | bold italic underline strikethrough | indent outdent | codesample | fontselect fontsizeselect forecolor backcolor | superscript subscript| formatpainter  removeformat ',
        toolbar_mode: 'sliding', //设置工具栏按钮数量超出时缩进抽屉（3个点的图标）
        //设置行尾回车时出现的快捷工具栏 注意：需要加载quickbars插件
        quickbars_insert_toolbar: '',
        //设置选中文本内容时出现的快捷工具栏
        quickbars_selection_toolbar:
          'removeformat | bold italic underline strikethrough | fontsizeselect forecolor backcolor',
        //设置需要进行加载的插件 注意：插件必须已存在于plugins目录下，默认不加载任何插件
        plugins:
          'link image table lists fullscreen quickbars paste codesample emoticons media formatpainter',
        language: 'zh_CN', //设置界面语言 注意：语言包必须放入langs目录下才可以使用language配置语言，否则需要使用language_url配置语言包具体路径
        // language_url: '/languages/zh_CN.js', //设置语言包的具体路径
        height: this.height, //设置编辑区高度
        branding: false, //隐藏富文本右下角技术支持
        statusbar: false, //隐藏富文本底部状态栏
        //处理文本换行时的行高问题
        force_br_newlines: true, //强制回车换行时生成</br>
        force_p_newlines: false, //强制关闭回车换行时生成<p></p>标签
        // forced_root_block: '', //强制初始化时的根标签为''，默认是<p>标签
        elementpath: false, //隐藏底栏的元素路径
        // images_upload_url: '/api/sys-storage/upload', //设置文件上传的url
        // images_upload_credentials: true, //设置是否传递cookie等跨域的凭据
        paste_data_images: true, //允许粘贴图片 注意：需要加载paste插件
        //自定义图片上传
        images_upload_handler: this.imagesUploadHandler,
        //正文粘贴
        paste_preprocess: this.contentPaste,
        file_picker_types: 'media',
        file_picker_callback: this.mediaUpload,
        convert_urls: false,
        waterMark: false
      },
      uploadVisible: false,
      uploaderCb: null,
      mediaToken: ''
    }
  },
  computed: {
    settings() {
      return { ...this.setting, ...this.customSetting }
    }
  },
  watch: {
    content(val) {
      if (this.value == val) {
        return
      }
      this.$emit('update:value', val)
    },
    value(val) {
      if (this.content == val) {
        return
      }

      this.content = val

      if (this.$refs['tinymce'] && this.$refs['tinymce'].setContent) {
        this.$refs['tinymce'].setContent(val)
      }
    }
  },
  created() {},
  mounted() {
    this.content = this.value
  },
  methods: {
    imagesUploadHandler(blobInfo, success, failure) {
      let formData = new FormData()

      //若不存在name属性，则blobInfo.blob()为blob对象，需转为file对象
      if (!blobInfo.blob().name) {
        const file = this.dataUrlToFile(
          blobInfo.blob().type,
          blobInfo.base64(),
          blobInfo.filename()
        )

        formData.append('file', file)
      } else {
        formData.append('file', blobInfo.blob())
      }

      //需要添加水印

      formData.append(
        'waterMarkJson',
        JSON.stringify({
          isWaterMark: this.settings.waterMark ? 1 : 0
        })
      )

      //添加desFileSize
      formData.append('desFileSize', 1024)
      uploadImage(formData)
        .then((res) => {
          if (res.status && res.data) {
            const url = this.getSrc(res.data.fileToken)
            success(url) //将上传图片的服务器url设置到img中
          } else {
            success(this.loseImg)
            // failure('图片上传发生错误')
          }
        })
        .catch((error) => {
          success(this.loseImg)
          // failure('图片上传发生错误')
        })
    },
    getSrc(fileToken) {
      let a = document.createElement('a')
      a.href = `${this.VUE_APP_DOWNLOAD_IMG_API}?f8s=${fileToken}`
      let url = a.href
      return url
    },
    //内容粘贴
    contentPaste(plugin, args) {
      if (args.content.length > 1024 * 1024) {
        this.$message.warning('一次性粘贴内容的过大，请分多次进行粘贴')
        args.content = ''
      }
    },
    /**
     * @description: 富文本上传视频回调方法
     */
    mediaUpload(cb, value, meta) {
      // console.log(cb, value, meta)
      this.mediaToken = value // 此处需要判断是否为凤翎视频
      this.uploaderCb = cb
      this.uploadVisible = true
    },
    //将blob对象转File
    dataUrlToFile(type, data, fileName) {
      let bstr = atob(data)
      let n = bstr.length
      let u8arr = new Uint8Array(n)

      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }

      return new File([u8arr], fileName, { type })
    }
  }
}
</script>

<style lang="scss" scoped>
</style>